/*
m_axis_user:
[79:64]icmp_seq
[63:48]icmp_id
[47:16]
[15:0]icmp_data_len

*/

module icmp_rx (
    input                       i_clk                       ,
    input                       i_rst                       ,
    input                       s_axis_tvalid               ,
    input  [7 : 0]              s_axis_tdata                ,
    input                       s_axis_tlast                ,
    input  [71: 0]              s_axis_tuser                ,
    output                      m_axis_tvalid               ,
    output [7 : 0]              m_axis_tdata                ,
    output                      m_axis_tlast                ,
    output [79: 0]              m_axis_tuser                     
);
    localparam  ICMP_PKG_TYPE   = 8'd1                          ;
    logic   [7 : 0]             icmp_axis_rx_tdata              ;
    logic   [71: 0]             icmp_axis_rx_tuser              ;
    logic                       icmp_axis_rx_tlast              ;
    logic                       icmp_axis_rx_tvalid             ;
    logic                       icmp_axis_rx_tvalid_1d          ;
    logic   [15: 0]             rx_cnt                          ;
    logic   [7 : 0]             icmp_type                       ;
    logic   [7 : 0]             icmp_code                       ;
    logic   [15: 0]             icmp_id                         ;
    logic   [15: 0]             icmp_seq                        ;
    logic   [7 : 0]             icmp_data                       ;
    logic                       icmp_last                       ;
    logic                       icmp_valid                      ;
    logic   [15: 0]             icmp_data_len                   ;


    assign m_axis_tvalid = icmp_valid;
    assign m_axis_tdata = icmp_data;
    assign m_axis_tlast = icmp_last;
    assign m_axis_tuser = {icmp_seq,icmp_id,icmp_axis_rx_tuser[55:24],icmp_data_len};

    //only recive the ip type is icmp and is not broadcast
    always_ff @(posedge i_clk) begin
        if(i_rst)
            icmp_axis_rx_tvalid <= 0;
        else if(s_axis_tuser[23:16] == ICMP_PKG_TYPE )
            icmp_axis_rx_tvalid <= s_axis_tvalid;
        else 
            icmp_axis_rx_tvalid <= 0;
    end

    always_ff @(posedge i_clk) begin
        if(i_rst) 
            icmp_axis_rx_tvalid_1d <= 0;
        else 
            icmp_axis_rx_tvalid_1d   <=  icmp_axis_rx_tvalid;
    end

    always_ff @(posedge i_clk) begin
        if(i_rst) begin
            icmp_axis_rx_tdata  <= 0;
            icmp_axis_rx_tuser  <= 0;
            icmp_axis_rx_tlast  <= 0;
        end 
        else  begin
            icmp_axis_rx_tdata   <=   s_axis_tdata ;
            icmp_axis_rx_tuser   <=   s_axis_tuser ;
            icmp_axis_rx_tlast   <=   s_axis_tlast ;
        end
    end

    always_ff @(posedge i_clk) begin
        if(i_rst)
            rx_cnt <= 0;
        else if(icmp_axis_rx_tvalid)
            rx_cnt <= rx_cnt + 1;
        else 
            rx_cnt <= 0;
    end

    always_ff @(posedge i_clk) begin
        if(i_rst)
            icmp_type <= 0;
        else if(rx_cnt ==0 && icmp_axis_rx_tvalid)
            icmp_type <= icmp_axis_rx_tdata;
        else 
            icmp_type <= icmp_type;
    end

    always_ff @(posedge i_clk) begin
        if(i_rst)
            icmp_code <= 0;
        else if(rx_cnt ==1 && icmp_axis_rx_tvalid)
            icmp_code <= icmp_axis_rx_tdata;
        else 
            icmp_code <= icmp_code;
    end

    always_ff @(posedge i_clk) begin
        if(i_rst)
            icmp_id <= 0;
        else if(rx_cnt >= 4 && rx_cnt <= 5)
            icmp_id <= {icmp_id[7 :0],icmp_axis_rx_tdata};
        else 
            icmp_id <= icmp_id;
    end
        
    always_ff @(posedge i_clk) begin
        if(i_rst)
            icmp_seq <= 0;
        else if(rx_cnt >= 6 && rx_cnt <= 7)
            icmp_seq <= {icmp_seq[7 :0],icmp_axis_rx_tdata};
        else 
            icmp_seq <= icmp_seq;
    end

    always_ff @(posedge i_clk) begin
        if(i_rst)
            icmp_data_len <= 0;
        else 
            icmp_data_len <= icmp_axis_rx_tuser[15:0] - 8;
    end
    
    always_ff @(posedge i_clk) begin
        if(i_rst)
            icmp_data <= 0;
        else 
            icmp_data <= icmp_axis_rx_tdata;
    end

    always_ff @(posedge i_clk) begin
        if(i_rst)
            icmp_last <= 0;
        else if(icmp_last & icmp_valid)
            icmp_last <= 0;
        else if(!s_axis_tvalid && icmp_axis_rx_tvalid && icmp_valid)
            icmp_last <= 1;
        else 
            icmp_last <= icmp_last;
    end

    always_ff @(posedge i_clk) begin
        if(i_rst)
            icmp_valid <= 'd0;
        else if(icmp_last & icmp_valid)
            icmp_valid <= 'd0;
        else if(rx_cnt == 8 && icmp_type == 8 && icmp_code == 0)
            icmp_valid <= 'd1;
        else 
            icmp_valid <= icmp_valid;
    end

endmodule
